#include "stdafx.h"
#include "CParamText.h"

Gdiplus::Color ARGB2Color(DWORD dwColor)
{
	return Gdiplus::Color(HIBYTE((dwColor) >> 16), GetBValue(dwColor), GetGValue(dwColor), GetRValue(dwColor));
}

CParamTextUI::CParamTextUI()
	: m_ParamReplace(nullptr)
{
}


CParamTextUI::~CParamTextUI()
{
}

LPCTSTR CParamTextUI::GetClass() const
{
	return _T("ParamText");
}

LPVOID CParamTextUI::GetInterface(LPCTSTR pstrName)
{
	if (_tcscmp(pstrName, _T("ParamText")) == 0) return static_cast<CParamTextUI*>(this);
	return CLabelUI::GetInterface(pstrName);
}

//void CParamTextUI::SetAttribute(LPCTSTR pstrName, LPCTSTR pstrValue)
//{
//	if (_tcscmp(pstrName, _T("text")) == 0 && m_ParamReplace)
//	{
//		DString dst = m_ParamReplace(pstrValue);
//		SetText(dst.GetData());
//	}
//	else
//		CLabelUI::SetAttribute(pstrName, pstrValue);
//}

void CParamTextUI::PaintText(HDC hDC)
{
	if (m_ParamReplace)
	{
		DString paintText = m_ParamReplace(m_sText);
		if (paintText.IsEmpty())
			paintText = m_sText;

		if (paintText.IsEmpty()) 
			return;

		if (m_dwTextColor == 0) m_dwTextColor = m_pManager->GetDefaultFontColor();
		if (m_dwDisabledTextColor == 0) m_dwDisabledTextColor = m_pManager->GetDefaultDisabledColor();

		RECT rc = m_rcItem;
		rc.left += m_rcTextPadding.left;
		rc.right -= m_rcTextPadding.right;
		rc.top += m_rcTextPadding.top;
		rc.bottom -= m_rcTextPadding.bottom;

		if (!GetEnabledEffect())
		{
			if (paintText.IsEmpty()) return;
			int nLinks = 0;
			if (IsEnabled()) {
				if (m_bShowHtml)
					CRenderEngine::DrawHtmlText(hDC, m_pManager, rc, paintText, m_dwTextColor, \
						NULL, NULL, nLinks, m_iFont, m_uTextStyle);
				else
					CRenderEngine::DrawText(hDC, m_pManager, rc, paintText, m_dwTextColor, \
						m_iFont, m_uTextStyle);
			}
			else {
				if (m_bShowHtml)
					CRenderEngine::DrawHtmlText(hDC, m_pManager, rc, paintText, m_dwDisabledTextColor, \
						NULL, NULL, nLinks, m_iFont, m_uTextStyle);
				else
					CRenderEngine::DrawText(hDC, m_pManager, rc, paintText, m_dwDisabledTextColor, \
						m_iFont, m_uTextStyle);
			}
		}
		else
		{
#ifdef _USE_GDIPLUS
			Gdiplus::Font	nFont(hDC, m_pManager->GetFont(GetFont()));
			Gdiplus::Graphics nGraphics(hDC);
			nGraphics.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);

			Gdiplus::StringFormat format;
			Gdiplus::StringAlignment sa = Gdiplus::StringAlignment::StringAlignmentNear;
			if ((m_uTextStyle & DT_VCENTER) != 0) sa = Gdiplus::StringAlignment::StringAlignmentCenter;
			else if ((m_uTextStyle & DT_BOTTOM) != 0) sa = Gdiplus::StringAlignment::StringAlignmentFar;
			format.SetLineAlignment((Gdiplus::StringAlignment)sa);
			sa = Gdiplus::StringAlignment::StringAlignmentNear;
			if ((m_uTextStyle & DT_CENTER) != 0) sa = Gdiplus::StringAlignment::StringAlignmentCenter;
			else if ((m_uTextStyle & DT_RIGHT) != 0) sa = Gdiplus::StringAlignment::StringAlignmentFar;
			format.SetAlignment((Gdiplus::StringAlignment)sa);

			RectF nRc((float)rc.left, (float)rc.top, (float)rc.right - rc.left, (float)rc.bottom - rc.top);
			RectF nShadowRc = nRc;
			nShadowRc.X += m_ShadowOffset.X;
			nShadowRc.Y += m_ShadowOffset.Y;

			int nGradientLength = GetGradientLength();

			if (nGradientLength == 0)
				nGradientLength = (rc.bottom - rc.top);

			Gdiplus::LinearGradientBrush nLineGrBrushA(Gdiplus::Point(GetGradientAngle(), 0), Gdiplus::Point(0, nGradientLength), ARGB2Color(GetTextShadowColorA()), ARGB2Color(GetTextShadowColorB() == -1 ? GetTextShadowColorA() : GetTextShadowColorB()));
			Gdiplus::LinearGradientBrush nLineGrBrushB(Gdiplus::Point(GetGradientAngle(), 0), Gdiplus::Point(0, nGradientLength), ARGB2Color(GetTextColor()), ARGB2Color(GetTextColor1() == -1 ? GetTextColor() : GetTextColor1()));

			if (GetEnabledLuminous())
			{
				// from http://bbs.csdn.net/topics/390346428
				int iFuzzyWidth = (int)(nRc.Width / GetLuminousFuzzy());
				if (iFuzzyWidth < 1) iFuzzyWidth = 1;
				int iFuzzyHeight = (int)(nRc.Height / GetLuminousFuzzy());
				if (iFuzzyHeight < 1) iFuzzyHeight = 1;
				Gdiplus::RectF nTextRc(0.0f, 0.0f, nRc.Width, nRc.Height);

				Gdiplus::Bitmap Bit1((INT)nRc.Width, (INT)nRc.Height);
				Gdiplus::Graphics g1(&Bit1);
				g1.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
				g1.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);
				g1.SetCompositingQuality(Gdiplus::CompositingQualityAssumeLinear);
				Gdiplus::Bitmap Bit2(iFuzzyWidth, iFuzzyHeight);
				Gdiplus::Graphics g2(&Bit2);
				g2.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic);
				g2.SetPixelOffsetMode(Gdiplus::PixelOffsetModeNone);

				Gdiplus::FontFamily ftFamily;
				nFont.GetFamily(&ftFamily);
				int iLen = wcslen(m_pWideText);
				g1.DrawString(m_pWideText, iLen, &nFont, nRc, &format, &nLineGrBrushB);

				g2.DrawImage(&Bit1, 0, 0, (int)iFuzzyWidth, (int)iFuzzyHeight);
				g1.Clear(Gdiplus::Color(0));
				g1.DrawImage(&Bit2, (int)m_ShadowOffset.X, (int)m_ShadowOffset.Y, (int)nRc.Width, (int)nRc.Height);
				g1.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);

				nGraphics.DrawImage(&Bit1, nRc.X, nRc.Y);
			}

			if (GetEnabledStroke() && GetStrokeColor() > 0)
			{
				Gdiplus::LinearGradientBrush nLineGrBrushStroke(Gdiplus::Point(GetGradientAngle(), 0), Gdiplus::Point(0, rc.bottom - rc.top + 2), ARGB2Color(GetStrokeColor()), ARGB2Color(GetStrokeColor()));
#ifdef _UNICODE
				nRc.Offset(-1, 0);
				nGraphics.DrawString(paintText, paintText.GetLength(), &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(2, 0);
				nGraphics.DrawString(paintText, paintText.GetLength(), &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(-1, -1);
				nGraphics.DrawString(paintText, paintText.GetLength(), &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(0, 2);
				nGraphics.DrawString(paintText, paintText.GetLength(), &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(0, -1);
#else
				int iLen = wcslen(m_pWideText);
				nRc.Offset(-1, 0);
				nGraphics.DrawString(m_pWideText, iLen, &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(2, 0);
				nGraphics.DrawString(m_pWideText, iLen, &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(-1, -1);
				nGraphics.DrawString(m_pWideText, iLen, &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(0, 2);
				nGraphics.DrawString(m_pWideText, iLen, &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(0, -1);
#endif	
			}
#ifdef _UNICODE
			if (GetEnabledShadow() && (GetTextShadowColorA() > 0 || GetTextShadowColorB() > 0))
				nGraphics.DrawString(paintText, paintText.GetLength(), &nFont, nShadowRc, &format, &nLineGrBrushA);

			nGraphics.DrawString(paintText, paintText.GetLength(), &nFont, nRc, &format, &nLineGrBrushB);
#else
			int iLen = wcslen(m_pWideText);
			if (GetEnabledShadow() && (GetTextShadowColorA() > 0 || GetTextShadowColorB() > 0))
				nGraphics.DrawString(m_pWideText, iLen, &nFont, nShadowRc, &format, &nLineGrBrushA);

			nGraphics.DrawString(m_pWideText, iLen, &nFont, nRc, &format, &nLineGrBrushB);
#endif
#endif
		}
	}
	else
	{
		CLabelUI::PaintText(hDC);
	}
}

void CParamTextUI::PaintTextOnCanvas(HDC hDC)
{
	if (m_ParamReplace)
	{
		DString paintText = m_ParamReplace(m_sText);
		if (paintText.IsEmpty())
			paintText = m_sText;

		if (paintText.IsEmpty())
			return;

		if (m_dwTextColor == 0) m_dwTextColor = m_pManager->GetDefaultFontColor();
		if (m_dwDisabledTextColor == 0) m_dwDisabledTextColor = m_pManager->GetDefaultDisabledColor();

		RECT rc = m_rcItemCanvas;
		rc.left += m_rcTextPadding.left;
		rc.right -= m_rcTextPadding.right;
		rc.top += m_rcTextPadding.top;
		rc.bottom -= m_rcTextPadding.bottom;

		if (!GetEnabledEffect())
		{
			if (paintText.IsEmpty()) return;
			int nLinks = 0;
			if (IsEnabled()) {
				if (m_bShowHtml)
					CRenderEngine::DrawHtmlText(hDC, m_pManager, rc, paintText, m_dwTextColor, \
						NULL, NULL, nLinks, m_iFont, m_uTextStyle);
				else
					CRenderEngine::DrawText(hDC, m_pManager, rc, paintText, m_dwTextColor, \
						m_iFont, m_uTextStyle);
			}
			else {
				if (m_bShowHtml)
					CRenderEngine::DrawHtmlText(hDC, m_pManager, rc, paintText, m_dwDisabledTextColor, \
						NULL, NULL, nLinks, m_iFont, m_uTextStyle);
				else
					CRenderEngine::DrawText(hDC, m_pManager, rc, paintText, m_dwDisabledTextColor, \
						m_iFont, m_uTextStyle);
			}
		}
		else
		{
#ifdef _USE_GDIPLUS
			Gdiplus::Font	nFont(hDC, m_pManager->GetFont(GetFont()));
			Gdiplus::Graphics nGraphics(hDC);
			nGraphics.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);

			Gdiplus::StringFormat format;
			Gdiplus::StringAlignment sa = Gdiplus::StringAlignment::StringAlignmentNear;
			if ((m_uTextStyle & DT_VCENTER) != 0) sa = Gdiplus::StringAlignment::StringAlignmentCenter;
			else if ((m_uTextStyle & DT_BOTTOM) != 0) sa = Gdiplus::StringAlignment::StringAlignmentFar;
			format.SetLineAlignment((Gdiplus::StringAlignment)sa);
			sa = Gdiplus::StringAlignment::StringAlignmentNear;
			if ((m_uTextStyle & DT_CENTER) != 0) sa = Gdiplus::StringAlignment::StringAlignmentCenter;
			else if ((m_uTextStyle & DT_RIGHT) != 0) sa = Gdiplus::StringAlignment::StringAlignmentFar;
			format.SetAlignment((Gdiplus::StringAlignment)sa);

			RectF nRc((float)rc.left, (float)rc.top, (float)rc.right - rc.left, (float)rc.bottom - rc.top);
			RectF nShadowRc = nRc;
			nShadowRc.X += m_ShadowOffset.X;
			nShadowRc.Y += m_ShadowOffset.Y;

			int nGradientLength = GetGradientLength();

			if (nGradientLength == 0)
				nGradientLength = (rc.bottom - rc.top);

			Gdiplus::LinearGradientBrush nLineGrBrushA(Gdiplus::Point(GetGradientAngle(), 0), Gdiplus::Point(0, nGradientLength), ARGB2Color(GetTextShadowColorA()), ARGB2Color(GetTextShadowColorB() == -1 ? GetTextShadowColorA() : GetTextShadowColorB()));
			Gdiplus::LinearGradientBrush nLineGrBrushB(Gdiplus::Point(GetGradientAngle(), 0), Gdiplus::Point(0, nGradientLength), ARGB2Color(GetTextColor()), ARGB2Color(GetTextColor1() == -1 ? GetTextColor() : GetTextColor1()));

			if (GetEnabledLuminous())
			{
				// from http://bbs.csdn.net/topics/390346428
				int iFuzzyWidth = (int)(nRc.Width / GetLuminousFuzzy());
				if (iFuzzyWidth < 1) iFuzzyWidth = 1;
				int iFuzzyHeight = (int)(nRc.Height / GetLuminousFuzzy());
				if (iFuzzyHeight < 1) iFuzzyHeight = 1;
				Gdiplus::RectF nTextRc(0.0f, 0.0f, nRc.Width, nRc.Height);

				Gdiplus::Bitmap Bit1((INT)nRc.Width, (INT)nRc.Height);
				Gdiplus::Graphics g1(&Bit1);
				g1.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias);
				g1.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);
				g1.SetCompositingQuality(Gdiplus::CompositingQualityAssumeLinear);
				Gdiplus::Bitmap Bit2(iFuzzyWidth, iFuzzyHeight);
				Gdiplus::Graphics g2(&Bit2);
				g2.SetInterpolationMode(Gdiplus::InterpolationModeHighQualityBicubic);
				g2.SetPixelOffsetMode(Gdiplus::PixelOffsetModeNone);

				Gdiplus::FontFamily ftFamily;
				nFont.GetFamily(&ftFamily);
				int iLen = wcslen(m_pWideText);
				g1.DrawString(m_pWideText, iLen, &nFont, nRc, &format, &nLineGrBrushB);

				g2.DrawImage(&Bit1, 0, 0, (int)iFuzzyWidth, (int)iFuzzyHeight);
				g1.Clear(Gdiplus::Color(0));
				g1.DrawImage(&Bit2, (int)m_ShadowOffset.X, (int)m_ShadowOffset.Y, (int)nRc.Width, (int)nRc.Height);
				g1.SetTextRenderingHint(Gdiplus::TextRenderingHintAntiAlias);

				nGraphics.DrawImage(&Bit1, nRc.X, nRc.Y);
			}

			if (GetEnabledStroke() && GetStrokeColor() > 0)
			{
				Gdiplus::LinearGradientBrush nLineGrBrushStroke(Gdiplus::Point(GetGradientAngle(), 0), Gdiplus::Point(0, rc.bottom - rc.top + 2), ARGB2Color(GetStrokeColor()), ARGB2Color(GetStrokeColor()));
#ifdef _UNICODE
				nRc.Offset(-1, 0);
				nGraphics.DrawString(paintText, paintText.GetLength(), &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(2, 0);
				nGraphics.DrawString(paintText, paintText.GetLength(), &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(-1, -1);
				nGraphics.DrawString(paintText, paintText.GetLength(), &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(0, 2);
				nGraphics.DrawString(paintText, paintText.GetLength(), &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(0, -1);
#else
				int iLen = wcslen(m_pWideText);
				nRc.Offset(-1, 0);
				nGraphics.DrawString(m_pWideText, iLen, &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(2, 0);
				nGraphics.DrawString(m_pWideText, iLen, &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(-1, -1);
				nGraphics.DrawString(m_pWideText, iLen, &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(0, 2);
				nGraphics.DrawString(m_pWideText, iLen, &nFont, nRc, &format, &nLineGrBrushStroke);
				nRc.Offset(0, -1);
#endif	
			}
#ifdef _UNICODE
			if (GetEnabledShadow() && (GetTextShadowColorA() > 0 || GetTextShadowColorB() > 0))
				nGraphics.DrawString(paintText, paintText.GetLength(), &nFont, nShadowRc, &format, &nLineGrBrushA);

			nGraphics.DrawString(paintText, paintText.GetLength(), &nFont, nRc, &format, &nLineGrBrushB);
#else
			int iLen = wcslen(m_pWideText);
			if (GetEnabledShadow() && (GetTextShadowColorA() > 0 || GetTextShadowColorB() > 0))
				nGraphics.DrawString(m_pWideText, iLen, &nFont, nShadowRc, &format, &nLineGrBrushA);

			nGraphics.DrawString(m_pWideText, iLen, &nFont, nRc, &format, &nLineGrBrushB);
#endif
#endif
		}
	}
	else
	{
		CLabelUI::PaintTextOnCanvas(hDC);
	}
}

void CParamTextUI::SetParamCallback(ParamReplaceCallback cb)
{
	m_ParamReplace = cb;
}
